package com.sigmatrix.h5.service.impl;

import java.util.ArrayList;
import java.util.Date;
import java.util.List;
import java.util.Map;
import java.util.stream.Collectors;

import org.apache.log4j.Logger;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import com.sigmatrix.h5.entity.CodeCirculation;
import com.sigmatrix.h5.entity.CodeMapping;
import com.sigmatrix.h5.entity.DisDealer;
import com.sigmatrix.h5.entity.DisRebateActivity;
import com.sigmatrix.h5.entity.DisRebateAudit;
import com.sigmatrix.h5.entity.DisRebateScanCode;
import com.sigmatrix.h5.entity.Product;
import com.sigmatrix.h5.enums.CrmAcctType;
import com.sigmatrix.h5.enums.PromotionCodeType;
import com.sigmatrix.h5.exception.MessageException;
import com.sigmatrix.h5.response.Response;
import com.sigmatrix.h5.service.CodeCirculationService;
import com.sigmatrix.h5.service.CodeMappingService;
import com.sigmatrix.h5.service.DisDealerAcctService;
import com.sigmatrix.h5.service.DisDealerService;
import com.sigmatrix.h5.service.DisRebateActivityService;
import com.sigmatrix.h5.service.DisRebateAuditService;
import com.sigmatrix.h5.service.DisRebateScanCodeService;
import com.sigmatrix.h5.service.HierarchyRebateService;
import com.sigmatrix.h5.service.InStorageService;
import com.sigmatrix.h5.service.ProductService;
import com.sigmatrix.h5.service.QrCodeService;
import com.sigmatrix.h5.service.common.ServiceHelper;
import com.sigmatrix.h5.utils.Assert;
import com.sigmatrix.h5.utils.CommonUtils;
import com.sigmatrix.h5.utils.Cons;
import com.sigmatrix.h5.utils.Constants;
import com.sigmatrix.h5.utils.SessionUtils;
import com.sigmatrix.h5.web.args.HierarchyRebate;
import com.sigmatrix.h5.web.args.HierarchyScan;
import com.sigmatrix.h5.web.args.SmallProgramTemplateMessage;
import com.sigmatrix.h5.web.mode.QrCode;
import com.sigmatrix.h5.web.mode.RebateActivityInfo;
import com.sigmatrix.h5.web.mode.RebateRecord.Rebate;
import com.sigmatrix.h5.web.vo.InStorageUpLoad;
import com.sigmatrix.sc.jdbc.common.lang.Session;
import com.sigmatrix.sc.rabbitmq.lang.RabbitSender;

/**
 * 
 *@ClassName: HierarchyRebateServiceImpl
 *@Description: 层级返利
 *@author MH
 *@date 2017年12月4日 下午4:46:40
 */
@Service
public class HierarchyRebateServiceImpl implements HierarchyRebateService{
	
	Logger logger = Logger.getLogger(this.getClass());
	
	@Autowired
	private DisDealerService disDealerService;
	
	@Autowired
	private DisRebateScanCodeService disRebateScanCodeService;
	
	@Autowired
	private DisDealerAcctService disDealerAcctService;
	
	@Autowired
	private DisRebateActivityService disRebateActivityService;
	
	@Autowired
	private DisRebateAuditService disRebateAuditService;
	
	@Autowired
	private QrCodeService qrCodeService;
	
	@Autowired
	private RabbitSender sender;

//	@Autowired
//	private FeignManager feignManager;
	
	/**入库业务层接口*/
	@Autowired
	private InStorageService inStorageService;
	
	@Autowired
	private ProductService productService;
	
	@Autowired
	private CodeCirculationService codeCirculationService;
	
	@Autowired
	private CodeMappingService codeMappingService;
	
	@Override
	@Transactional
	public QrCode scanCode(HierarchyRebate scan) {
		//1.先根据扫码内容校验码信息
		scan.setQrCode(CommonUtils.encodeQRCode(scan.getQrCode()));
		QrCode code = qrCodeService.findByQrCode(scan.getQrCode());
		validateQRCode(code);
		try {
			//2.查询扫码记录
			List<DisRebateScanCode> scanHistory = null;
			if(CommonUtils.isEmpty(code.getParallelCode())){
				scanHistory = disRebateScanCodeService.findScanHistory(scan.getQrCode());
			}else{
				scanHistory = disRebateScanCodeService.findScanHistory2_6(scan.getQrCode(),code.getParallelCode());
			}
			//确定当前登录的用户所在的经销商
			Map<Integer, String> dealers = disDealerAcctService.getDealers(scan.getDealerId());
			DisDealer dealer;
			DisRebateActivity activity;
			DisRebateScanCode lastScanRecord = null;
			List<Rebate> rebates =null;
			//3.根据是否是首次扫码确定返利活动
			if(CommonUtils.isNotEmpty(scanHistory)){
				lastScanRecord = scanHistory.get(0);
				Assert.notNull(lastScanRecord.getDealerId(), "没有记录上次扫码的经销商，无法返利");
				if(CrmAcctType.TERMINAL_SHOP.value.equals(lastScanRecord.getScanType()))throw new MessageException("该码已经被终端店扫过");
//				//3.1先根据经纬度判断有没有窜货
//				boolean fleeing = disDealerService.checkFleeing(lastScanRecord.getDealerId(), scan.getLat(), scan.getLng());
//				if(!fleeing)throw new MessageException("GPS定位地点没有在上级经销商的销售区域");
				//3.2确定返利的经销商
				List<DisDealer> _dealers = disRebateScanCodeService.determineRebateDealers(scanHistory,dealers);
				boolean fleeing = disDealerService.checkFleeing(lastScanRecord.getDealerId(), scan.getLat(), scan.getLng());
				if(!fleeing) {
					_dealers = new ArrayList<>();
				}
				//定位没有串货就分析是否出库
				if(CommonUtils.isNotEmpty(_dealers)) {
					//去除未扫码出库的经销商
					_dealers = delDealers(scan.getQrCode(),_dealers);
				}
				//3.3如果有扫码记录，就按上次的活动返利
				activity = disRebateActivityService.findById(lastScanRecord.getRebateActivityId());
				//校验活动时间（有可能上级经销商扫码以后，流转到下级经销商，活动已经结束）
				disRebateActivityService.validateActivity(activity);
				rebates = disRebateAuditService.apply(activity, (dealer=_dealers.get(_dealers.size()-1)).getLevel(), PromotionCodeType.DEALER.value,_dealers.toArray(new DisDealer[_dealers.size()]));
			}else{
				if(dealers.size() > 1){throw new MessageException(Constants.PARAM_ERROR,"请选择经销商");}
				else if(dealers.size()<1){throw new MessageException("终端店没有关联经销商，不能扫码");}
				//确定返利活动
				dealer = disDealerService.findById(dealers.keySet().iterator().next());
				//if(Short.valueOf("1").equals(dealer.getLevel()))throw new MessageException("一级经销商不允许扫码");
				
//				boolean fleeing = disDealerService.checkFleeing(dealer.getId(), scan.getLat(), scan.getLng());
//				if(!fleeing)throw new MessageException("GPS定位地点没有在上级经销商的销售区域");
				List<DisDealer> parents = disDealerService.findParentsByPromotionCode(dealer.getPromotionCode());
				DisDealer first = null;
				for (DisDealer distributionDealers : parents) {
					if(Short.valueOf("1").equals(distributionDealers.getLevel())){
						first = distributionDealers;
						break;
					}
				}
				Assert.notNull(first, "没有查询到一级经销商");
				boolean fleeing = disDealerService.checkFleeing(dealer.getId(), scan.getLat(), scan.getLng());
				//定位串货只给终端店返利
				if(!fleeing) {
					parents = new ArrayList<>();
				}
				//定位没有串货就分析是否出库
				if(CommonUtils.isNotEmpty(parents)) {
					//去除未扫码出库的经销商
					parents = delDealers(scan.getQrCode(),parents);
				}
				RebateActivityInfo activityInfo = disRebateActivityService.determineActivityForHierarchyRebate(first.getId(), code.getProductId());
				rebates = disRebateAuditService.apply((activity = disRebateActivityService.getActivity(activityInfo)), dealer.getLevel(), PromotionCodeType.DEALER.value,parents.toArray(new DisDealer[parents.size()]));
			}
			//修改经销商库存
			updateInStorageCount(dealer.getCode(),
					CommonUtils.isEmpty(lastScanRecord)?null:lastScanRecord.getDealerCode(),
							code.getProductCode(), SessionUtils.getAcctType(), null, scan.getQrCode());
			//保存扫码记录
			Integer scanId = saveScanHistory(dealer, code.getProductId(), code.getPackLevel().shortValue(), code.getSeqNum(), activity.getId(), scan);
			//TODO 更新扫码记录id到返利表（时间紧急先这样写，后期优化）
			if (CommonUtils.isNotEmpty(rebates)) {
				DisRebateAudit audit =  null;
				for (Rebate rebate : rebates) {
					audit = disRebateAuditService. findById(rebate.getAuditId());
					if(CommonUtils.isNotEmpty(audit)) {
						audit.setScanCodeId(scanId);
						disRebateAuditService.updateSelective(audit);
					}
				}
			}
		} catch (Exception e) {
			logger.error("错误：", e);
			throw new MessageException(null	, e.getMessage(), code);
		}
		return code;
	}
	
	/**
	 * 通过防伪码查询天鉴码的物流码并加密
	 * @param qrCode
	 * @return
	 */
	private String getQrcode(String qrCode) {
		//酒鬼酒的库存表和码流转表使用物流码的加密信息进行查询
		CodeMapping mapping = codeMappingService.findByQrCode(qrCode);
		Assert.notNull(mapping, "码不存在,没有在mapping表");
		return CommonUtils.encodeQRCode(mapping.getLogisticsCode());
	}


	/**
	 * 根据qrCode查询码流转信息，如果销售出库信息中，没有当前扫码的上级经销商，则移除该上级经销商
	 *
	 *@return void
	 *@author wjwei
	 *@date 2018年3月21日 下午4:38:02
	 *@param qrCode
	 *@param _dealers
	 */
	private List<DisDealer> delDealers(String qrCode, List<DisDealer> _dealers) {
		List<DisDealer> rebateDealers = new ArrayList<>();
		if(ServiceHelper.isJiuGuiJiu(SessionUtils.getEseCode())) {
			qrCode = getQrcode(qrCode);
		}
		List<CodeCirculation> codeCirculations = codeCirculationService.findListByQrCode(qrCode);
		if(CommonUtils.isNotEmpty(codeCirculations)) {
			List<String> codes = new ArrayList<>();
			for (CodeCirculation codeCirculation : codeCirculations) {
				codes.add(codeCirculation.getOrganizationCode());
			}
			for (DisDealer dealer : _dealers) {
				if(codes.contains(dealer.getCode())) {
					rebateDealers.add(dealer);
				}
			}
		}
		return rebateDealers;
	}


	/**
	 * 修改经销商库存
	 * 
	 *@return void
	 *@author wjwei
	 *@date 2018年3月20日 下午5:47:42
	 *@param dealerCode
	 *@param parentCode
	 *@param productCode
	 *@param tag
	 *@param userId
	 *@param qrCode
	 */
	private void updateInStorageCount(String dealerCode,String parentCode, String productCode, Short tag, Integer userId, String qrCode) {
		if(ServiceHelper.isJiuGuiJiu(SessionUtils.getEseCode())) {
			qrCode = getQrcode(qrCode);
		}
		InStorageUpLoad inStorageUpLoad = InStorageUpLoad.build(dealerCode,parentCode, productCode, tag, userId, qrCode);
		Response result = null;
		try{
			result = inStorageService.receiptInStorage(inStorageUpLoad);
		}catch(Exception e){
			throw new MessageException("修改库存失败,请联系管理员");
		}
		if(Cons.RESPONSE_CODE_SUCCESS != result.getCode())throw new MessageException(result.getMessage());
	}


	private void validateQRCode(QrCode code){
		Assert.notNull(code.getProductId(), "码没有关联产品ID");
		Assert.notNull(code.getPackLevel(), "码没有包装级别");
		Product product = productService.findById(code.getProductId());
		Assert.notNull(product, "码无效，产品ID错误");
		code.setProductCode(product.getCode());
		/**
		 * 验证当前码是否为最大包装码（即活动的码级别）
		 * 目前：活动的码级别 暂时写在产品的packLevel上，后面可能需要调整，请知悉。
		 */
		if(!code.getPackLevel().equals(product.getPackLevel())) {
			throw new MessageException("当前码未参加活动");
		}
	}
	private Integer saveScanHistory(DisDealer dealer,Integer productId ,Short codeType,String seqNum,Integer activityId,HierarchyRebate scan){
		DisRebateScanCode _scan = new DisRebateScanCode();
		_scan.setCodeType(codeType);
		_scan.setOpenId(scan.getOpenId());
		_scan.setQrCode(scan.getQrCode());
		_scan.setRebateActivityId(activityId);
		_scan.setSeqNum(seqNum);
		_scan.setAccount(SessionUtils.getAccount());
		_scan.setStatus(Constants.STATUS_ENABLE);
		_scan.setDealerId(dealer.getId());
		if(CrmAcctType.TERMINAL_SHOP.value.equals(SessionUtils.getAcctType())) {
			_scan.setScanId(SessionUtils.getTerminalShopId());
			_scan.setScanType(CrmAcctType.TERMINAL_SHOP.value);
		}
		else if (CrmAcctType.DEALER.value.equals(SessionUtils.getAcctType())) {
			_scan.setScanId(SessionUtils.getDealerId());
			_scan.setScanType(CrmAcctType.DEALER.value);
		}
		_scan.setDealerCode(dealer.getCode());
		_scan.setScanTime(new Date());
		_scan.setProductId(productId);
		return disRebateScanCodeService.insertSelective(_scan);
	}

	@Override
	public void submitTask(HierarchyScan scan) {
		Assert.notNull(scan.getQrCode(), "你没有扫码不能提交");
		for (String qrCode : scan.getQrCode()) {
			Assert.notNull(qrCode, "其中有一个码内容为空，不能提交");
		}
		//如果是终端店话，判断关联几个经销商
		if(CommonUtils.isEmpty(scan.getDealerId())){
			Map<Integer, String> dealers = disDealerAcctService.getDealers(null);
			if(dealers.size()>1){
				List<DisDealer> list = dealers.keySet().stream().map(x -> disDealerService.findById(x))
				.collect(Collectors.toList());
				throw new MessageException(Constants.PARAM_ERROR,"请选择经销商",list);
			}else if(dealers.size()<1){throw new MessageException("终端店没有关联经销商，不能扫码");}
		}
		scan.setUser(Session.get());
		SmallProgramTemplateMessage info = scan.getMessageInfo();
		Assert.notNull(scan.getMessageInfo(), "小程序信息不能为空");
		Assert.notNull(info.getOpenId(), "openId不能为空");
		Assert.notNull(scan.getQrCode(), "码内容不能为空");
		info.setOpenId(info.getOpenId());
		sender.send(1,scan);
		
	}
}
